package com.axend.sofa.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import cn.com.heaton.blelibrary.ble.model.BleDevice
import cn.com.heaton.blelibrary.ble.utils.ByteUtils
import com.axend.lib_base.R
import com.axend.lib_base.base.vm.BaseViewModel
import com.axend.lib_base.engine.toast.toast
import com.axend.lib_base.help.ble.BleClient
import com.axend.lib_base.help.ble.BleMsgProcessor
import com.axend.lib_base.help.ble.enums.BleCommandTag
import com.axend.lib_base.utils.ByteUtil
import com.axend.lib_base.utils.CommUtils
import com.axend.lib_base.utils.log.MyLogUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.IOException

class FirmwareUpdateViewModel : BaseViewModel() {
    /*固件路径*/
    private var _firmwarePath: MutableLiveData<String> = MutableLiveData()
    val firmwarePath: LiveData<String> get() = _firmwarePath

    /*固件版本*/
    private var _firmwareVersion: MutableLiveData<String> = MutableLiveData()
    val firmwareVersion: LiveData<String> get() = _firmwareVersion

    /*固件文件crc16*/
    private var _firmwareCrc16: MutableLiveData<Array<ByteArray>> = MutableLiveData()

    /*固件文件总帧数*/
    private var _firmwareTotalFrame: MutableLiveData<Int> = MutableLiveData(0)
    val firmwareTotalFrame: LiveData<Int> get() = _firmwareTotalFrame

    /*固件文件已上传帧数*/
    private var _firmwareCurrentFrame: MutableLiveData<Int> = MutableLiveData(0)
    val firmwareCurrentFrame: LiveData<Int> get() = _firmwareCurrentFrame


    /*固件文件字节数组*/
    private var _fileBuffer: MutableLiveData<ByteArray> = MutableLiveData()
    val fileBuffer: LiveData<ByteArray> get() = _fileBuffer

    /*下发升级是否成功*/
    private var _firmwareUpdateSuccess: MutableLiveData<Boolean> = MutableLiveData(false)
    val firmwareUpdateSuccess: LiveData<Boolean> get() = _firmwareUpdateSuccess

    private val mutex = Mutex()

    /**
     * 设置固件路径
     */
    fun setFirmwarePath(path: String) {
        launchOnUI {
            _firmwarePath.postValue(path)
            val fileInputStream = FileInputStream(path)
            val fileBuffer = ByteArray(fileInputStream.available())
            _fileBuffer.postValue(fileBuffer)
            fileInputStream.read(fileBuffer)
            fileInputStream.close()

            _firmwareCrc16.value = ByteUtil.splitAndCrc16(fileBuffer, 256)
            _firmwareCrc16.value?.let {
                _firmwareTotalFrame.postValue(it.size)
            }
        }
    }


    /**
     * 设置固件版本
     */
    fun setFirmwareVersion(version: String) {
        launchOnUI {
            _firmwareVersion.postValue(version)
        }
    }


    fun writeFirmwareUpdateMsg() {
        launchOnUI {
            try {
                /*下发固件长度*/
                _fileBuffer.value?.let {
                    val msg = BleMsgProcessor.encodeFirmwareUpdateMsg(
                        ByteUtil.intToByteLittle(it.size),
                        BleCommandTag.FW_UPGRADE_NOTIFY
                    )
                    writeBleMsg(msg)
                }
            } catch (e: FileNotFoundException) {
                throw RuntimeException(e)
            } catch (e: IOException) {
                throw RuntimeException(e)
            }

        }
    }


    fun writeBleMsg(byteArray: ByteArray) {
        launchOnUI {
            withContext(Dispatchers.IO) {
                BleClient.writeData(byteArray, object : BleClient.OnBleWriteCallback {
                    override fun onWriteSuccess(device: BleDevice, data: ByteArray) {
                        /*写入成功后返回的消息处理*/
//                        MyLogUtils.w("固件回复消息：${ByteUtils.toHexString(data)}")
                        val msgPair = BleMsgProcessor.decodeFirmwareUpdateMsg(data)
                        when (msgPair?.first) {
                            BleCommandTag.FW_UPGRADE_NOTIFY -> {
                                launchOnUI {
                                    if (msgPair.second[0] == 0x01.toByte()) {
                                        /*开始下发固件内容第一帧*/
                                        _firmwareCurrentFrame.value = 0
                                        if (!_firmwareCrc16.value.isNullOrEmpty()) {
                                            val firmwareMsg =
                                                BleMsgProcessor.encodeFirmwareUpdateMsg(
                                                    _firmwareCrc16.value!![_firmwareCurrentFrame.value!!],
                                                    BleCommandTag.FW_CONTENT
                                                )
                                            writeBleMsg(firmwareMsg)
                                            MyLogUtils.w("开始固件下发，固件下发帧数：${_firmwareCurrentFrame.value}.总帧数：${_firmwareTotalFrame.value}")

                                        }
                                        incrementFirmwareCurrentFrame()
                                    } else {
                                        toast(CommUtils.getString(R.string.app_tips_set_failed))
                                    }
                                }
                            }

                            BleCommandTag.FW_CONTENT -> {
                                //固件下发成功
                                launchOnUI {
//                                    MyLogUtils.e("上一次固件内容回复帧数：${ByteUtil.bytes2IntLittle(msgPair.second)}")
                                    if (msgPair.second.isNotEmpty()) {
                                        if (ByteUtil.bytes2IntLittle(msgPair.second) != 0) {
                                            // 检查当前帧数和总帧数是否合法
                                            val currentFrame = _firmwareCurrentFrame.value ?: 0
                                            val totalFrame = _firmwareTotalFrame.value ?: 0

                                            if (currentFrame < totalFrame) {
                                                val firmwareMsg =
                                                    BleMsgProcessor.encodeFirmwareUpdateMsg(
                                                        _firmwareCrc16.value!![currentFrame],
                                                        BleCommandTag.FW_CONTENT
                                                    )
                                                delay(80)
                                                writeBleMsg(firmwareMsg)
                                            }
                                            // 检查是否完成下发
                                            if (currentFrame >= totalFrame) {
                                                try {
                                                    // 下发升级完成指令
                                                    val firmwareMsg =
                                                        BleMsgProcessor.encodeFirmwareUpdateMsg(
                                                            BleCommandTag.FW_UPDATE_SUCCESS.getMarkFixCommand(),
                                                            BleCommandTag.FW_UPDATE_SUCCESS
                                                        )
                                                    writeBleMsg(firmwareMsg)
                                                } catch (e: Exception) {
                                                    MyLogUtils.e(
                                                        "固件升级完成指令下发失败: ${e.message}",
                                                        e.message.toString()
                                                    )
                                                }
                                            }
                                            MyLogUtils.w("固件下发帧数：${currentFrame}.总帧数：${totalFrame}")
                                            // 更新当前帧数
                                            incrementFirmwareCurrentFrame()
//                                           _firmwareCurrentFrame.value=currentFrame + 1

                                        } else {
////                                    //下发失败从第一帧开始
//                                    _firmwareCurrentFrame.postValue(0)
//                                    val firmwareMsg = BleMsgProcessor.encodeFirmwareUpdateMsg(
//                                        _firmwareCrc16.value!![_firmwareCurrentFrame.value!!], BleCommandTag.FW_CONTENT)
//                                    writeBleMsg(firmwareMsg)
//                                    MyLogUtils.w("固件下发失败，重新下发，固件下发帧数：${_firmwareCurrentFrame.value}.总帧数：${_firmwareTotalFrame.value}")
//                                    _firmwareCurrentFrame.postValue(_firmwareCurrentFrame.value!! + 1)
                                        }
                                    }
                                }
                            }

                            BleCommandTag.FW_UPDATE_SUCCESS -> {
                                /*flash拷贝 等待15秒才会应答*/
                                if (msgPair.second[0] == 0x01.toByte()) {
                                    writeBleMsg(
                                        BleMsgProcessor.encodeMsg(
                                            BleCommandTag.GET_VERSION.getMarkFixCommand(),
                                            BleCommandTag.GET_VERSION
                                        ))
                                    _firmwareUpdateSuccess.postValue(true)
                                } else {
                                    _firmwareUpdateSuccess.postValue(false)
                                }
                            }

                            BleCommandTag.GET_VERSION -> {
                                setFirmwareVersion(
                                    "V${
                                        com.axend.lib_base.utils.ByteUtils.byteArrayToCommaSeparatedString(
                                            msgPair.second
                                        )
                                    }"
                                )
                            }

                            else -> {

                            }
                        }
                    }

                    override fun onWriteFailed(device: BleDevice, errorCode: Int) {
                        toast("errorCode:${errorCode}")
                    }

                })
            }
        }
    }

    private suspend fun incrementFirmwareCurrentFrame() {
        mutex.withLock {
            val currentFrame = _firmwareCurrentFrame.value ?: 0
            _firmwareCurrentFrame.value = currentFrame + 1
        }
    }
}